/**
 * Matrix Framework ABP vNext 核心服务
 * 集成ABP框架的前端核心功能
 */

import { ref, reactive } from 'vue'
import axios from 'axios'
import type {
  AbpCoreConfiguration,
  AbpResponse,
  AbpRequestOptions,
  AbpLogInfo,
  AbpNotificationInfo,
  AbpTenantResolveResult,
  AbpUserInfo,
  AbpTenantInfo,
  AbpPermissionInfo,
  AbpFeatureInfo,
  AbpSettingInfo
} from '@/types/abp'

class AbpService {
  private static instance: AbpService
  public config: AbpCoreConfiguration
  public isInitialized = ref(false)
  public isLoading = ref(false)
  public errors = ref<string[]>([])

  // ABP核心数据
  public session = reactive({
    tenant: undefined as AbpTenantInfo | undefined,
    user: undefined as AbpUserInfo | undefined
  })

  public localization = reactive({
    currentCulture: { cultureName: 'zh-CN', displayName: '简体中文' },
    languages: [],
    resources: {} as any
  })

  public auth = reactive({
    grantedPolicies: {} as Record<string, boolean>
  })

  public features = reactive({
    values: {} as Record<string, any>
  })

  public settings = reactive({
    values: {} as Record<string, string>
  })

  // 事件系统
  private eventListeners = new Map<string, Function[]>()

  private constructor() {
    this.config = this.getDefaultConfiguration()
    this.setupAxiosInterceptors()
  }

  /**
   * 获取单例实例
   */
  static getInstance(): AbpService {
    if (!AbpService.instance) {
      AbpService.instance = new AbpService()
    }
    return AbpService.instance
  }

  /**
   * 初始化ABP服务
   */
  async initialize(): Promise<void> {
    if (this.isInitialized.value) {
      return
    }

    try {
      this.isLoading.value = true
      this.clearErrors()

      // 加载基础配置
      await this.loadConfiguration()

      // 加载本地化资源
      await this.loadLocalization()

      // 加载权限信息
      await this.loadPermissions()

      // 加载功能设置
      await this.loadFeatures()

      // 加载用户设置
      await this.loadSettings()

      this.isInitialized.value = true
      this.emit('initialized')

      console.log('ABP服务初始化成功')
    } catch (error) {
      console.error('ABP服务初始化失败:', error)
      this.addError(`ABP初始化失败: ${this.getErrorMessage(error)}`)
      this.emit('error', error)
      throw error
    } finally {
      this.isLoading.value = false
    }
  }

  /**
   * 获取默认配置
   */
  private getDefaultConfiguration(): AbpCoreConfiguration {
    return {
      apis: {
        default: {
          url: process.env.VUE_APP_API_BASE_URL || 'http://localhost:5000'
        }
      },
      localization: {
        currentCulture: {
          cultureName: 'zh-CN',
          displayName: '简体中文'
        },
        languages: [
          {
            cultureName: 'zh-CN',
            displayName: '简体中文',
            isDisabled: false,
            isDefault: true
          },
          {
            cultureName: 'en',
            displayName: 'English',
            isDisabled: false,
            isDefault: false
          }
        ],
        resources: {}
      },
      auth: {
        grantedPolicies: {}
      },
      features: {
        values: {}
      },
      setting: {
        values: {}
      },
      session: {
        tenant: undefined,
        user: undefined
      },
      timing: {
        timeZoneInfo: {
          windows: {
            timeZoneId: 'China Standard Time',
            currentUtcOffset: '+08:00',
            isDaylightSavingTime: false
          },
          iana: {
            timeZoneId: 'Asia/Shanghai'
          }
        }
      }
    }
  }

  /**
   * 设置axios拦截器
   */
  private setupAxiosInterceptors(): void {
    // 请求拦截器
    axios.interceptors.request.use(
      (config) => {
        // 添加ABP特有的头部
        config.headers = config.headers || {}
        config.headers['X-Requested-With'] = 'XMLHttpRequest'

        // 添加租户头部
        if (this.session.tenant?.id) {
          config.headers['X-Tenant-Id'] = this.session.tenant.id
        }

        // 添加语言头部
        config.headers['Accept-Language'] = this.localization.currentCulture.cultureName

        // 添加防CSRF头部
        const token = this.getAntiForgeryToken()
        if (token) {
          config.headers['RequestVerificationToken'] = token
        }

        return config
      },
      (error) => {
        console.error('ABP请求拦截器错误:', error)
        return Promise.reject(error)
      }
    )

    // 响应拦截器
    axios.interceptors.response.use(
      (response) => {
        // 检查ABP格式响应
        const data = response.data
        if (data && typeof data === 'object' && data.__abp) {
          if (!data.success) {
            throw new Error(data.error?.message || '请求失败')
          }
        }
        return response
      },
      async (error) => {
        const originalRequest = error.config

        // 处理401未授权错误
        if (error.response?.status === 401 && !originalRequest._abpRetry) {
          originalRequest._abpRetry = true
          this.emit('unauthorized')
          throw error
        }

        // 处理403禁止访问错误
        if (error.response?.status === 403) {
          this.emit('forbidden')
          throw error
        }

        // 处理ABP错误响应
        if (error.response?.data?.error) {
          const abpError = error.response.data.error
          const message = abpError.details || abpError.message || '请求失败'
          this.addError(message)
          this.emit('error', message)
        }

        return Promise.reject(error)
      }
    )
  }

  /**
   * 加载配置信息
   */
  private async loadConfiguration(): Promise<void> {
    try {
      const response = await axios.get('/api/abp/application-configuration')
      const config = response.data

      // 更新配置
      if (config.auth) {
        Object.assign(this.auth.grantedPolicies, config.auth.grantedPolicies)
      }
      if (config.features) {
        Object.assign(this.features.values, config.features.values)
      }
      if (config.setting) {
        Object.assign(this.settings.values, config.setting.values)
      }
      if (config.localization) {
        Object.assign(this.localization, config.localization)
      }
      if (config.session) {
        Object.assign(this.session, config.session)
      }

      Object.assign(this.config, config)
    } catch (error) {
      console.warn('加载ABP配置失败:', error)
      // 使用默认配置
    }
  }

  /**
   * 加载本地化资源
   */
  private async loadLocalization(): Promise<void> {
    try {
      const cultureName = this.localization.currentCulture.cultureName
      const response = await axios.get(`/api/abp/localization/${cultureName}`)
      const resources = response.data

      this.localization.resources = resources
    } catch (error) {
      console.warn('加载本地化资源失败:', error)
    }
  }

  /**
   * 加载权限信息
   */
  private async loadPermissions(): Promise<void> {
    try {
      const response = await axios.get('/api/abp/permissions')
      const permissions = response.data

      this.auth.grantedPolicies = permissions.grantedPolicies || {}
    } catch (error) {
      console.warn('加载权限信息失败:', error)
    }
  }

  /**
   * 加载功能设置
   */
  private async loadFeatures(): Promise<void> {
    try {
      const response = await axios.get('/api/abp/features')
      const features = response.data

      this.features.values = features.values || {}
    } catch (error) {
      console.warn('加载功能设置失败:', error)
    }
  }

  /**
   * 加载用户设置
   */
  private async loadSettings(): Promise<void> {
    try {
      const response = await axios.get('/api/abp/settings')
      const settings = response.data

      this.settings.values = settings.values || {}
    } catch (error) {
      console.warn('加载用户设置失败:', error)
    }
  }

  /**
   * 检查权限
   */
  hasPermission(permissionName: string): boolean {
    return !!this.auth.grantedPolicies[permissionName] ||
           !!this.auth.grantedPolicies['*'] || // 超级管理员权限
           !!this.auth.grantedPolicies[`${permissionName}.*`] // 通配符权限
  }

  /**
   * 检查功能是否启用
   */
  isFeatureEnabled(featureName: string): boolean {
    const value = this.features.values[featureName]
    return value !== false && value !== 'false'
  }

  /**
   * 获取功能值
   */
  getFeatureValue(featureName: string): any {
    return this.features.values[featureName]
  }

  /**
   * 获取设置值
   */
  getSetting(settingName: string): string {
    return this.settings.values[settingName] || ''
  }

  /**
   * 获取本地化文本
   */
  localize(key: string, resourceName?: string): string {
    const resources = resourceName
      ? this.localization.resources[resourceName]?.texts
      : Object.values(this.localization.resources).reduce((acc, resource) => {
          return { ...acc, ...(resource?.texts || {}) }
        }, {})

    return resources?.[key] || key
  }

  /**
   * 设置当前租户
   */
  setTenant(tenant?: AbpTenantInfo): void {
    this.session.tenant = tenant
    this.emit('tenantChanged', tenant)
  }

  /**
   * 设置当前用户
   */
  setUser(user?: AbpUserInfo): void {
    this.session.user = user
    this.emit('userChanged', user)
  }

  /**
   * 切换语言
   */
  async changeLanguage(cultureName: string): Promise<void> {
    try {
      await axios.post('/api/abp/localization/change-language', { cultureName })
      this.localization.currentCulture.cultureName = cultureName
      this.emit('languageChanged', cultureName)
    } catch (error) {
      console.error('切换语言失败:', error)
      throw error
    }
  }

  /**
   * 日志记录
   */
  log(logInfo: AbpLogInfo): void {
    console.log(`[ABP Log] ${logInfo.level}: ${logInfo.message}`, logInfo)
    this.emit('log', logInfo)
  }

  /**
   * 通知处理
   */
  handleNotification(notification: AbpNotificationInfo): void {
    console.log(`[ABP Notification] ${notification.name}: ${notification.message}`, notification)
    this.emit('notification', notification)
  }

  /**
   * 解析租户
   */
  async resolveTenant(tenantName?: string): Promise<AbpTenantResolveResult> {
    try {
      const response = await axios.post('/api/abp/multi-tenancy/resolve-tenant', { tenantName })
      return response.data
    } catch (error) {
      console.error('解析租户失败:', error)
      throw error
    }
  }

  /**
   * 事件监听
   */
  on(event: string, callback: Function): void {
    if (!this.eventListeners.has(event)) {
      this.eventListeners.set(event, [])
    }
    this.eventListeners.get(event)!.push(callback)
  }

  /**
   * 移除事件监听
   */
  off(event: string, callback?: Function): void {
    if (!this.eventListeners.has(event)) {
      return
    }

    if (callback) {
      const callbacks = this.eventListeners.get(event)!
      const index = callbacks.indexOf(callback)
      if (index > -1) {
        callbacks.splice(index, 1)
      }
    } else {
      this.eventListeners.delete(event)
    }
  }

  /**
   * 触发事件
   */
  private emit(event: string, ...args: any[]): void {
    const callbacks = this.eventListeners.get(event)
    if (callbacks) {
      callbacks.forEach(callback => {
        try {
          callback(...args)
        } catch (error) {
          console.error(`事件处理器执行错误 [${event}]:`, error)
        }
      })
    }
  }

  /**
   * 获取防CSRF令牌
   */
  private getAntiForgeryToken(): string | null {
    const tokenElement = document.querySelector('input[name="__RequestVerificationToken"]') as HTMLInputElement
    return tokenElement?.value || null
  }

  /**
   * 添加错误信息
   */
  private addError(error: string): void {
    this.errors.value.push(error)
  }

  /**
   * 清除错误信息
   */
  private clearErrors(): void {
    this.errors.value = []
  }

  /**
   * 获取错误消息
   */
  private getErrorMessage(error: any): string {
    if (typeof error === 'string') {
      return error
    }

    if (error.response?.data?.error?.message) {
      return error.response.data.error.message
    }

    if (error.message) {
      return error.message
    }

    return '未知错误'
  }

  /**
   * 重置ABP服务
   */
  reset(): void {
    this.isInitialized.value = false
    this.clearErrors()

    // 重置会话信息
    this.session.tenant = undefined
    this.session.user = undefined

    // 重置权限信息
    this.auth.grantedPolicies = {}

    // 重置功能设置
    this.features.values = {}

    // 重置用户设置
    this.settings.values = {}

    // 重新加载配置
    this.config = this.getDefaultConfiguration()
  }
}

// 创建单例实例
const abpService = AbpService.getInstance()

export default abpService
export { AbpService }
export type { AbpCoreConfiguration }